package org.queryexecutor.main;

import java.awt.Component;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.Timer;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.queryexecutor.database.DatabaseConnection;
import org.queryexecutor.database.drivers.DatabaseDrivers;
import org.queryexecutor.swing.dialogs.DatabaseLogin;
import org.queryexecutor.swing.frames.MainFrame;
import org.queryexecutor.threads.CheckUpdates;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Main
{
	
	private static Properties configuration;
	private DatabaseConnection dbConnection;
	private Document dom;
	private Timer t;
	
	private ArrayList<DatabaseDrivers> drivers;

	public Main()
	{
		configuration = new Properties();
		this.dbConnection = DatabaseConnection.getInstance();
		this.drivers = new ArrayList<DatabaseDrivers>();
	}
	
	public void configure() throws FileNotFoundException, IOException
	{
		configuration.load(new FileInputStream("./config/config.ini"));
	}
	
	public void parseXMLConfiguration(String url) throws ParserConfigurationException, SAXException, IOException, SQLException, InstantiationException, IllegalAccessException, ClassNotFoundException
	{
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		
		this.dom = db.parse(url);
		Element element = this.dom.getDocumentElement();
		NodeList list = element.getElementsByTagName("driver");
		if(list != null && list.getLength() > 0) {
			for(int ctr = 0; ctr < list.getLength(); ctr++) {
				Element el = (Element) list.item(ctr);
				DatabaseDrivers driver =  new DatabaseDrivers();
				driver.setDatabaseType(el.getAttribute("id"));
				driver.setDriver(el.getAttribute("class"));
				driver.setConnectionString(el.getAttribute("url"));
				driver.setType(el.getAttribute("type"));
				this.dbConnection.addDriver(driver.getDriver());//this.dbConnection.getClass();//
				this.drivers.add(driver);
			}
		}
	}
	
	public static void main(String[] args)
	{
		System.setProperty("sun.awt.noerasebackground", "true");
		Main main = new Main();
		MainFrame mainFrame = MainFrame.getInstance();
		DatabaseLogin loginFrame = DatabaseLogin.getInstance(mainFrame);
		try {
			main.configure();
			main.parseXMLConfiguration(configuration.getProperty("driver.configuration.file"));
			mainFrame.setLocationRelativeTo(null);
			mainFrame.setVisible(true);
			//loginFrame.setModal(false);
			loginFrame.instantiateMethods();
			loginFrame.setDatabases(main.drivers);
			loginFrame.setLocationRelativeTo(mainFrame);
			loginFrame.setResizable(false);
			loginFrame.setVisible(true);
		} catch(Exception e) {
			showException(e, null);
		}
	}
	
	public static void showException(Exception e, Component parent)
	{
		StringBuilder message = new StringBuilder(e.getClass().toString());
		message.append(": ").append(e.getMessage());
		message.append("\nTrace:\n");
		StackTraceElement[] trace = e.getStackTrace();
		for(int ctr = 0; ctr < trace.length && ctr < 10; ctr++){
			message.append("\t").append(trace[ctr]).append("\n");
		}
		System.out.println(message.toString());
		showMessage(null, message.toString(), true);
	}
	
	public static void showMessage(Component parent, String message, boolean isError)
	{
		if(isError){
			JOptionPane.showMessageDialog(parent, message, "Error", JOptionPane.ERROR_MESSAGE);
		}else{
			JOptionPane.showMessageDialog(parent, message, "Message", JOptionPane.INFORMATION_MESSAGE);
		}
	}
	
	public static String getProperty(String key)
	{
		return configuration.getProperty(key);
	}
	
	public void startCheckUpdateThread(long period) throws MalformedURLException
	{
		this.t = new Timer(true);
		this.t.scheduleAtFixedRate(new CheckUpdates(Main.getProperty("update.url")), period, period);
	}
}
